package com.woniuxy.configuration;
/*
 * @author 幸琦林
 *
 */
import java.util.LinkedHashMap;
import java.util.Map;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.woniuxy.realm.UserRealm;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;


@Configuration
public class ShiroConfiguration {
    //realm
    @Bean    //默认将方法名作为id
    public UserRealm realm(CredentialsMatcher credentialsMatcher) {
        UserRealm realm = new UserRealm();
        //开启缓存
        realm.setCachingEnabled(true);
        //设置认证缓存
        realm.setAuthenticationCachingEnabled(true);
        realm.setAuthenticationCacheName("abc");
        //设置授权的缓存
        realm.setAuthorizationCachingEnabled(true);
        realm.setAuthorizationCacheName("cba");

        realm.setCredentialsMatcher(credentialsMatcher);
        return realm;
    }

    //    覆盖默认CredentialsMatcher的匹配方法，加入标识符免密返回成功
    @Bean
    public RetryLimitHashedCredentialsMatcher CredentialsMatcher() {
        RetryLimitHashedCredentialsMatcher retryLimitHashedCredentialsMatcher = new RetryLimitHashedCredentialsMatcher();
        retryLimitHashedCredentialsMatcher.setHashAlgorithmName("MD5");
        return retryLimitHashedCredentialsMatcher;
    }

    //securityManager
    @Bean    //参数的名字要与上边方法的名字保持一致
    public SecurityManager securityManager(UserRealm realm) {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        //设置realm
        manager.setRealm(realm);
        //直接调方法获取缓存管理器
        manager.setCacheManager(ehCacheManager());
//        设置记住我管理器
        manager.setRememberMeManager(rememberMeManager());
        return manager;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

    //过滤器
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        //设置安全管理器
        factoryBean.setSecurityManager(securityManager);
        //登录页面
        factoryBean.setLoginUrl("/xingqilin/Login.html");
        //没权限时显示的页面
        factoryBean.setUnauthorizedUrl("/xingqilin/Login.html");
        //设置过滤器链
        Map<String, String> map = new LinkedHashMap<>();    //有序
        //设置

//        测试时全开放，需要删除
//        map.put("/**", "anon");

        map.put("/xingqilin/Login.html", "anon");
//        静态资源放行
        map.put("/js/**", "anon");
        map.put("/css/**", "anon");
        map.put("/images/**", "anon");
        map.put("/img/**", "anon");
        map.put("/bootstrap/**", "anon");
        map.put("/layui/**", "anon");
        map.put("/vue/**", "anon");
        map.put("/fonts/**", "anon");
//         请求页面放行
        map.put("/home/**", "anon");
        map.put("/coach/**", "anon");
        map.put("/logout", "logout");

        map.put("/**", "user");

        //设置
        factoryBean.setFilterChainDefinitionMap(map);

        return factoryBean;
    }

    //    配置shiro对thymeleaf模板引擎支持的对象
    @Bean
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }

    /*
     * 注解
     */
    //生命周期管理器
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);
        return creator;
    }


    /*
     * 缓存
     */
    @Bean
    public EhCacheManager ehCacheManager() {
        EhCacheManager manager = new EhCacheManager();
        //加载配置文件
        manager.setCacheManagerConfigFile("classpath:ehcache.xml");
        return manager;
    }

    /**
     * cookie对象;
     * rememberMeCookie()方法是设置Cookie的生成模版，比如cookie的name，cookie的有效时间等等。
     *
     * @return
     */
    @Bean
    public SimpleCookie rememberMeCookie() {
        System.out.println("ShiroConfiguration.rememberMeCookie()");
        //这个参数是cookie的名称，对应前端的checkbox的name = rememberMe
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        //<!-- 记住我cookie生效时间30天 ,单位秒;-->
        simpleCookie.setMaxAge(86400);
        return simpleCookie;
    }

    /**
     * cookie管理对象;
     * rememberMeManager()方法是生成rememberMe管理器，而且要将这个rememberMe管理器设置到securityManager中
     *
     * @return
     */
    @Bean
    public CookieRememberMeManager rememberMeManager() {
        System.out.println("ShiroConfiguration.rememberMeManager()");
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookie());
        cookieRememberMeManager.setCipherKey(Base64.decode("6ZmI6I2j5Y+R5aSn5ZOlAA=="));
        return cookieRememberMeManager;
    }

    /**
     * FormAuthenticationFilter 过滤器 过滤记住我
     * <p>
     * 增加免密登录功能，使用自定义过滤器覆盖原有token生成器
     *
     * @return
     */
    @Bean
    public EasyFormAuthenticationFilter formAuthenticationFilter() {
//        原有过滤器
//        FormAuthenticationFilter formAuthenticationFilter = new FormAuthenticationFilter();
        EasyFormAuthenticationFilter formAuthenticationFilter = new EasyFormAuthenticationFilter();

        //对应前端的checkbox的name = rememberMe
        formAuthenticationFilter.setUsernameParam("account");
        formAuthenticationFilter.setPasswordParam("pwd");
        formAuthenticationFilter.setRememberMeParam("rememberMe");

        return formAuthenticationFilter;
    }


}






